/*
 * *************************************************************************************
 *  Copyright (C) 2006-2015 EsperTech, Inc. All rights reserved.                       *
 *  http://www.espertech.com/esper                                                     *
 *  http://www.espertech.com                                                           *
 *  ---------------------------------------------------------------------------------- *
 *  The software in this package is published under the terms of the GPL license       *
 *  a copy of which has been included with this distribution in the license.txt file.  *
 * *************************************************************************************
 */

package com.zhangyang.esper.pattern;

import com.espertech.esper.client.*;
import com.espertech.esper.client.scopetest.SupportUpdateListener;
import com.espertech.esper.client.time.CurrentTimeEvent;
import com.espertech.esper.common.internal.support.SupportBean;
import junit.framework.TestCase;

import java.util.List;
import java.util.UUID;

public class TestNotOperator extends TestCase
{

    public void testNotTimeInterval()
    {
        Configuration config = new Configuration();
        config.getEngineDefaults().getThreading().setInternalTimerEnabled(true);

        config.addEventType("A", SupportBean.class);

        EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(config);
        epService.initialize();
        String stmtText = "select * from pattern [ every b=A ->( timer:interval(20 seconds) and not A(intPrimitive=0) where timer:within(120 seconds))  ]";
        EPStatement statement = epService.getEPAdministrator().createEPL(stmtText);
        SupportUpdateListener listener = new SupportUpdateListener();
        statement.addListener(listener);

        sendTimer(0, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("\\E1\\E2", 123));
        //如果触发时间为10s，那么会返回e1
        sendTimer(10000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E2", 123));
        assertFalse(listener.isInvoked());
        sendTimer(30000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E3", 123));
        //如果触发间隔是20s，此时已经40了，触发两次，所有e1作为触发第一次得，E2作为触发第二次
        assertFalse(listener.isInvoked());
//        listener.reset(); 不加这个配置，容易像滑动窗口那样产生很多次触发，来一条检测一次，如果触发了进行reset就可以间隔多久触发一次
        sendTimer(31000, epService);
        assertFalse(listener.isInvoked());

        sendTimer(32000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E4", 1));
        assertFalse(listener.isInvoked());
        sendTimer(51000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E5", 1));
        sendTimer(52000, epService);
        assertFalse(listener.isInvoked());
        listener.reset();

        List<EventBean[]> newDataList = listener.getNewDataList();
        assertFalse(newDataList.size()>0);

    }
    public void testNotTimeNotInterval() throws InterruptedException {
        Configuration config = new Configuration();
        config.getEngineDefaults().getThreading().setInternalTimerEnabled(true);


        config.addEventType("A", SupportBean.class);

        EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(config);
        epService.initialize();
        String stmtText = "@Audit('result') select  uuidString() as uuid   from pattern [ every (timer:interval(20 seconds) and not A(intPrimitive=0) where timer:within(120 seconds))  ]";
        EPStatement statement = epService.getEPAdministrator().createEPL(stmtText);
//        epService.getEPRuntime().sendEvent(new SupportBean("E4", 1));
        SupportUpdateListener listener = new SupportUpdateListener();
        statement.addListener(listener);
        Thread.sleep(60000);
        List<EventBean[]> newDataList = listener.getNewDataList();
        Thread.sleep(60000);
        List<EventBean[]> newDataList1 = listener.getNewDataList();
        Thread.sleep(60000);
        List<EventBean[]> newDataList2 = listener.getNewDataList();
        Thread.sleep(60000);
        List<EventBean[]> newDataList3 = listener.getNewDataList();
    }

    public void testNotAll()
    {
        Configuration config = new Configuration();
        config.getEngineDefaults().getThreading().setInternalTimerEnabled(false);

        config.addEventType("A", SupportBean.class);
        config.addImport(UUID.class);
        config.addPlugInSingleRowFunction("uuidString",TestNotOperator.class.getName(),"uuidString");
        EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(config);


        epService.initialize();
        String stmtText = "select uuidString() as alert\n" +
                "from pattern [ every (timer:interval(20) and not A where timer:within(120 seconds)) ]";
        EPStatement statement = epService.getEPAdministrator().createEPL(stmtText);
        SupportUpdateListener listener = new SupportUpdateListener();
        statement.addListener(listener);

        sendTimer(0, epService);
        //需要一个初始化得数据触发流程
        epService.getEPRuntime().sendEvent(new SupportBean());
//        epService.getEPRuntime().sendEvent(new SupportBean("E1", 123));
        //如果触发时间为10s，那么会返回e1
        sendTimer(10000, epService);
//        epService.getEPRuntime().sendEvent(new SupportBean("E2", 123));
        assertFalse(listener.isInvoked());
        sendTimer(30000, epService);
//        epService.getEPRuntime().sendEvent(new SupportBean("E3", 123));
        //如果触发间隔是20s，此时已经40了，触发两次，所有e1作为触发第一次得，E2作为触发第二次
        assertFalse(listener.isInvoked());
//        listener.reset(); 不加这个配置，容易像滑动窗口那样产生很多次触发，来一条检测一次，如果触发了进行reset就可以间隔多久触发一次
        sendTimer(31000, epService);
        assertFalse(listener.isInvoked());

        sendTimer(32000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E4", 1));
        assertFalse(listener.isInvoked());
        sendTimer(51000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E5", 1));
        sendTimer(52000, epService);
        assertFalse(listener.isInvoked());
        listener.reset();

        List<EventBean[]> newDataList = listener.getNewDataList();
        assertFalse(newDataList.size()>0);
    }

    public static String uuidString() {
        return UUID.randomUUID().toString();
    }

    public void testBeforeNotOccur(){
        Configuration config = new Configuration();
        config.getEngineDefaults().getThreading().setInternalTimerEnabled(false);

        config.addEventType("A", SupportBean.class);
        EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(config);
        epService.initialize();
        String stmtText = "select * " +
                "from pattern [ every b=A -> ( and not A() where timer:within(120 seconds)) ]";
        EPStatement statement = epService.getEPAdministrator().createEPL(stmtText);
        SupportUpdateListener listener = new SupportUpdateListener();
        statement.addListener(listener);

        sendTimer(0, epService);
        //需要一个初始化得数据触发流程
        epService.getEPRuntime().sendEvent(new SupportBean());
        epService.getEPRuntime().sendEvent(new SupportBean("E1", 123));
        //如果触发时间为10s，那么会返回e1
        sendTimer(10000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E2", 123));
        assertFalse(listener.isInvoked());
        sendTimer(30000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E3", 123));
        //如果触发间隔是20s，此时已经40了，触发两次，所有e1作为触发第一次得，E2作为触发第二次
        assertFalse(listener.isInvoked());
//        listener.reset(); 不加这个配置，容易像滑动窗口那样产生很多次触发，来一条检测一次，如果触发了进行reset就可以间隔多久触发一次
        sendTimer(31000, epService);
        assertFalse(listener.isInvoked());

        sendTimer(32000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E4", 1));
        assertFalse(listener.isInvoked());
        sendTimer(51000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E5", 1));
        sendTimer(52000, epService);
        assertFalse(listener.isInvoked());
        listener.reset();

        List<EventBean[]> newDataList = listener.getNewDataList();
        assertFalse(newDataList.size()>0);
    }
    public void testAfterNotOccur(){
        Configuration config = new Configuration();
        config.getEngineDefaults().getThreading().setInternalTimerEnabled(false);

        config.addEventType("A", SupportBean.class);
        EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(config);
        epService.initialize();
        String stmtText = "select 'No event within 20 seconds' as alert\n" +
                "from pattern [ every (timer:interval(20) and not A where timer:within(120 seconds)) ]";
        EPStatement statement = epService.getEPAdministrator().createEPL(stmtText);
        SupportUpdateListener listener = new SupportUpdateListener();
        statement.addListener(listener);

        sendTimer(0, epService);
        //需要一个初始化得数据触发流程
        epService.getEPRuntime().sendEvent(new SupportBean());
//        epService.getEPRuntime().sendEvent(new SupportBean("E1", 123));
        //如果触发时间为10s，那么会返回e1
        sendTimer(10000, epService);
//        epService.getEPRuntime().sendEvent(new SupportBean("E2", 123));
        assertFalse(listener.isInvoked());
        sendTimer(30000, epService);
//        epService.getEPRuntime().sendEvent(new SupportBean("E3", 123));
        //如果触发间隔是20s，此时已经40了，触发两次，所有e1作为触发第一次得，E2作为触发第二次
        assertFalse(listener.isInvoked());
//        listener.reset(); 不加这个配置，容易像滑动窗口那样产生很多次触发，来一条检测一次，如果触发了进行reset就可以间隔多久触发一次
        sendTimer(31000, epService);
        assertFalse(listener.isInvoked());

        sendTimer(32000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E4", 1));
        assertFalse(listener.isInvoked());
        sendTimer(51000, epService);
        epService.getEPRuntime().sendEvent(new SupportBean("E5", 1));
        sendTimer(52000, epService);
        assertFalse(listener.isInvoked());
        listener.reset();

        List<EventBean[]> newDataList = listener.getNewDataList();
        assertFalse(newDataList.size()>0);
    }
    private void sendTimer(long timeInMSec, EPServiceProvider epService)
    {
        CurrentTimeEvent theEvent = new CurrentTimeEvent(timeInMSec);
        EPRuntime runtime = epService.getEPRuntime();
        runtime.sendEvent(theEvent);
    }
}
